#include "blockQueue.hpp"
#include <ctime>
#include <unistd.h>
#include "Thread.hpp"
#include "Task.hpp"

void productorR(void *args){
    //pthread_detach(pthread_self());
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    string opers = "+-*/%";
    while(true){
        sleep(1);
        int x = rand() % 20 + 1;
        int y = rand() % 20 + 1;
        char op = opers[rand() % opers.size()];
        Task task(x, y, op);
        bq->push(task);
        cout << pthread_self() << " | productor Task: " << task.formatArg() << "?" << endl;
    }
}

void consumerR(void *args){
    //pthread_detach(pthread_self());
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    while(true){
        Task task;
        bq->pop(&task);
        task();
        cout << pthread_self() << " | consumer data: " << task.formatArg() << task.formatRes() << endl;
    }
}

int main(){
    srand((uint64_t)time(nullptr) ^ getpid());
    BlockQueue<Task> *bq = new BlockQueue<Task>();

    Thread productor1(1, productorR, bq);
    Thread productor2(2, productorR, bq);
    Thread productor3(3, productorR, bq);
    Thread consumer2(2, consumerR, bq);
    Thread consumer1(1, consumerR, bq);

    productor1.run();
    productor2.run();
    productor3.run();
    consumer1.run();
    consumer2.run();

    productor1.join();
    productor2.join();
    productor3.join();
    consumer1.join();
    consumer2.join();

    delete bq;
    return 0;
}